const nodemailer = require('nodemailer')
const { email, info, server } = require('../config')
const { authCode, template_info } = require('../templates')
const { ServerError, AuthFailed } = require('../core/http-exception')
const { SP_ADMIN } = require('../middleware/auth')
const redis = require('./redis')
const exception = require('./exception')

class Email {
  constructor() {
    this.transporter = nodemailer.createTransport({
      service: email.service,
      port: email.port,
      secureConnection: true,
      auth: {
        user: email.user,
        pass: email.pass
      }
    })

    this.defaultOption = {
      from: `${info.title} <${email.user}>`
    }
  }

  getTypeTitle(option) {
    switch (option.type) {
      case 'authcode':
        return `你好！你的验证码来啦(${option.title})`
      default:
        return option.title || '这是一封我们也不知道啥用处的邮件'
    }
  }

  getTypeHtml(option) {
    let content = option.content || option.title || "";
    switch (option.type) {
      case 'authcode':
        return authCode(content, option.code);
      case 'disable_article':
        return template_info(`
          您的《${option.article_title}》文章，被管理员(${option.admin_name})禁用，如果想要发布，请修改违规内容！ <br/>
          违规内容说明: ${option.info}
        `)
      case 'request_unlock_article':
        return template_info(`
          用户${option.article_user_username}的文章《${option.article_title}》请求解封，请前往处理。
        `, '管理员')
      case 'unlock_article':
        return template_info(`
          您的文章《${option.article_title}》${
            option.info ? '解禁请求被驳回 <br/> 驳回理由: ' + option.info : '成功解禁为草稿状态，请前往草稿箱自行发布'
          }
        `)
      default:
        return '这封邮件是一个意外';
    }
  }

  send(option) {
    this.defaultOption.subject = `${info.title} - ` + this.getTypeTitle(option)
    this.defaultOption.html = this.getTypeHtml(option)
    this.defaultOption.to = option.to

    return new Promise((resolve, reject) => {
      this.transporter.sendMail(this.defaultOption, (error, info) => {
        try {
          if (error) {
            console.warn(
              '邮件发送失败：' + error.message + '; 邮件发送对象: ' + option.to
            )
            throw new ServerError('邮件发送失败')
          }
        } catch (err) {
          exception(option.ctx, err)
          resolve(false)
        }
        resolve(true)
      })
    })
  }

  async delay(key, m, level = 1) {
    if (level < SP_ADMIN) {
      const delay = await redis.get('content', key + '-delay')
      if (delay) {
        throw new AuthFailed(`发送此类邮件需要冷却${m / 60}分钟`)
      }
      await redis.set('content', key + '-delay', true, 60)
    }
  }
}

const Mailer = new Email()

module.exports = Mailer
